package com.krt.facenettydemo.netty;

import android.content.Context;
import android.os.Handler;
import android.util.Log;

import org.json.JSONException;
import org.json.JSONObject;

import java.io.IOException;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.TimeUnit;

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.AdaptiveRecvByteBufAllocator;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.FixedRecvByteBufAllocator;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.DelimiterBasedFrameDecoder;
import io.netty.handler.codec.FixedLengthFrameDecoder;
import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
import io.netty.handler.codec.LengthFieldPrepender;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
import io.netty.handler.timeout.IdleStateHandler;

/**
 * @author Marcus
 * @package krt.wid.tour_gz.net.netty
 * @description
 * @time 2018/12/4
 */

public class NettyClient {
    public final String TAG = "HeartBeatReqHandler";

    EventLoopGroup group = new NioEventLoopGroup();

    final Timer timer = new Timer();

    private Handler handler;

    //通道
    private Channel channel;

    public Channel getChannel() {
        return channel;
    }

    public static NettyClient getInstance() {
        return NettyClient.SingleonHolder.INSTANCE;
    }


    public void bind(final Context context, final String ip, final Handler handler) throws Exception {
        try {
            this.handler = handler;
            Bootstrap bootstrap = new Bootstrap();
            bootstrap.group(group)
                    .channel(NioSocketChannel.class)
                    .option(ChannelOption.TCP_NODELAY, true)
//                    .option(ChannelOption.RCVBUF_ALLOCATOR, new FixedRecvByteBufAllocator(2048 * 10))
                    .handler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        public void initChannel(SocketChannel ch) throws IOException {
                            //超时机制
                            ch.pipeline().addLast(new IdleStateHandler(30, 30, 10, TimeUnit.SECONDS));
//                            ByteBuf delimiter = Unpooled.copiedBuffer("\r\n".getBytes());
                            ch.pipeline().addLast(new ChannelHandler[]{new LengthFieldBasedFrameDecoder(2147483647, 0, 4, 0, 4)});
                            //定义包头长度
                            ch.pipeline().addLast(new LengthFieldPrepender(4));
                            //编码器
                            ch.pipeline().addLast(new StringDecoder());
                            //解码器
                            ch.pipeline().addLast(new StringEncoder());
                            //超时处理
                            ch.pipeline().addLast("nettyHandler", new NettyHandler());
                        }
                    });
            // 发起异步链接操作
            ChannelFuture channelFuture = bootstrap.connect(ip, 16500).sync();
            if (channelFuture.isSuccess()) {
                if (handler != null) {
                    handler.sendEmptyMessage(0);
                }
                Log.w("netty", "连接成功");
            }
            channel = channelFuture.channel();
            channelFuture.channel().closeFuture().sync();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            timer.scheduleAtFixedRate(new TimerTask() {
                public void run() {
                    try {
                        Log.w(TAG, "Netty断线重连");
                        bind(context, ip, handler);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }, 1000, 5 * 1000);
        }
    }

    public void unBind() {
        channel.close();
        timer.cancel();
    }

    /**
     * 对比成功发送消息给服务端
     *
     * @param result:0通过， 1不通过
     */
    public void sendMsg(String idcard, int result) {
        //{"id":"3623311998112711", "result":"0"}
        try {
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("id", idcard);
            jsonObject.put("result", result);
            if (channel != null) {
                channel.writeAndFlush(jsonObject.toString());
            }
        } catch (JSONException e) {
            e.printStackTrace();
        }

    }

    private static class SingleonHolder {
        private static final NettyClient INSTANCE = new NettyClient();

        private SingleonHolder() {
        }
    }

}
